#ifndef  _T_SOCKET_H_
#define  _T_SOCKET_H_

#include "../define/define.h"
#include "../util/log.h"
#include "../util/timer.h"

class  t_socket_server
{
public:
   t_socket_server(uint16 port)
   {
	   func_lock s_lock;
	   m_log = new logfile("t_socket_server");
	   m_socket = socket(PF_INET,SOCK_STREAM,0);

	   if(m_socket == -1)
		   return;

	   int opt=SO_REUSEADDR;
       setsockopt(m_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); 

	   setnonblocking(m_socket);
	   
	   sockaddr_in my_addr;
	   memset(&my_addr, 0, sizeof(sockaddr_in));
       my_addr.sin_family = PF_INET;
       my_addr.sin_port = htons(port);
	   
	   if(-1 == bind(m_socket, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)))
	   {
 		   close_socket(m_socket);
	       return;
	   }
	   
	   if (listen(m_socket, 20) == -1) 
		   close_socket(m_socket);
	
	   m_port = port;
   }

   ~t_socket_server()
   {
	   func_lock s_lock;
	   delete m_log;
	   if (m_socket != 0) 
	      close_socket(m_socket);
   }

   void setnonblocking(uint32 socket)
   {
		int opts;
		opts=fcntl(socket,F_GETFL);
		if(opts<0)
		{
			return;
		}

		opts = opts|O_NONBLOCK;
		if(fcntl(socket,F_SETFL,opts)<0)
		{
			return;
		}

		//m_log->WriteTrace("setnonblocking ok");
   }

   int  sendbuf(uint32 socket, char* buf, uint32 buf_size)
   {	
	   int size = send(socket,buf,buf_size,0);
	   
	   if(size == -1 && errno != EAGAIN)
	   {
			char tmp_str[1024] = {0};
			sprintf(tmp_str,"send socket=%d is error,errno=%d",
				 socket,errno);
			m_log->WriteTrace(tmp_str);
			return -1;
	   }

	   if(size == -1)
		   size = 0;

	   return size;
   }

   int recvbuf(uint32 socket, char* buf, int buf_size)
   {
	   int size = 0;
	   size = recv(socket,buf,buf_size,0);

	   if(size == -1 && errno != EAGAIN)
	   {
		   	char tmp_str[1024] = {0};
			sprintf(tmp_str,"recv socket=%d is error,errno=%d",
				 socket,errno);
			m_log->WriteTrace(tmp_str);

		   return -1;
	   }

	    if(size == -1)
		   size = 0;

	   return size;
   }

   bool accept_scoket(uint32* socket,sockaddr* sock_addr)
   {
	   func_lock s_lock;
	   sockaddr socket_out;
	   socklen_t len;
       memset(&socket_out,0,sizeof(sockaddr));
	   uint32 new_fd = accept(m_socket,&socket_out,&len);

	   if(new_fd == -1 && errno == EAGAIN )
	   {
		    if (errno != EAGAIN && errno != ECONNABORTED   
            && errno != EPROTO && errno != EINTR)   
               m_log->WriteTrace("accept_scoket error"); 

		    return false;
	   }

	   //if(new_fd == 0)
	   // return false;

	   setnonblocking(new_fd);
       
       *socket = new_fd;
       *sock_addr = socket_out;
	   return true;
   }
   
   bool close_socket(uint32 socket)
   {
	   func_lock s_lock;
	   
	   	char tmp_str[1024] = {0};
	 	sprintf(tmp_str,"delete socket=%d",socket);
   		m_log->WriteTrace(tmp_str);


	   if(close(socket) == -1)
	   {
			char tmp_str[1024] = {0};
			sprintf(tmp_str,"socket error=,socket=%d,errno=%d",
				 socket,errno);
			m_log->WriteTrace(tmp_str);
			return false;
	   }
	 
      return true;
   }

   uint32 get_socket()
   {
       return m_socket;
   }

private:
	
	uint32      m_socket;
    sockaddr    m_socket_in;

	uint16      m_port;
	logfile*    m_log;
};


#endif
